<?php

namespace App\Logic\Member;

use App\Core\BaseCore;
use App\Core\BaseModel;
use App\Core\Output;
use App\Logic\Member\Form\ScoreGroupListForm;
use App\Logic\Member\Form\ScoreListForm;
use App\Model\Account\CashoutModel;
use App\Model\Member\MemberModel;
use App\Model\Member\MemberScoreModel;
use App\Util\ArrayHelper;
use App\Util\CommonHelper;
use App\Util\UserIdentityHelper;
use EasySwoole\Component\Di;
use EasySwoole\Component\Singleton;
use EasySwoole\Http\Request;
use EasySwoole\Mysqli\QueryBuilder;
use EasySwoole\ORM\DbManager;
use EasySwoole\ORM\Exception\Exception;
use EasySwoole\Redis\Redis;
use Throwable;

class MemberScoreService extends BaseCore
{

    use Singleton;

    /**
     * 字典数据
     * @param $data
     * @return Output
     * @throws Exception
     * @throws Throwable
     */
    public function getDict(Request $request) : Output
    {
        $result = [
            'type'   => ArrayHelper::keyArrayToList(MemberScoreModel::getTypeDict()),
        ];

        return $this->success($result);
    }

    /**
     * 积分流水列表 getLists
     * @param Request $request
     * @return Output
     * @throws Throwable
     * @throws \EasySwoole\Redis\Exception\RedisException
     */
    public function getLists(Request $request):Output
    {
        $params = $request->getQueryParams();
        /** @var Redis $cache */
        $cache     = Di::getInstance()->get("REDIS");
        $cache_key = "memberScoreCache:scoreList:" . json_encode($params + ['_id' => UserIdentityHelper::getId(), '_name' => UserIdentityHelper::getUsername()]);
        if ($cache_data = $cache->get($cache_key)) { //缓存存在
            $data = json_decode($cache_data, true);
        } else {
            $form = new ScoreListForm($params, $request);
            $data = $form->lists();
            $cache->set($cache_key, json_encode($data), BaseModel::CACHE_EXPIRE);
        }
        return $this->success($data);
    }

    /**
     * 积分流水列表 按日期分组
     * @param Request $request
     * @return Output
     * @throws Throwable
     * @throws \EasySwoole\Redis\Exception\RedisException
     */
    public function getGroupLists(Request $request):Output
    {
        $params = $request->getQueryParams();
        /** @var Redis $cache */
        $cache     = Di::getInstance()->get("REDIS");
        $cache_key = "memberScoreCache:scoreGroupList:" . json_encode($params + ['_id' => UserIdentityHelper::getId(), '_name' => UserIdentityHelper::getUsername()]);
        if ($cache_data = $cache->get($cache_key)) { //缓存存在
            $data = json_decode($cache_data, true);
        } else {
            $form = new ScoreGroupListForm($params, $request);
            $data = $form->lists();
            $cache->set($cache_key, json_encode($data), BaseModel::CACHE_EXPIRE);
        }
        return $this->success($data);
    }

    /**
     * 积分变动
    */
    public function change($user_id, $score, $type, $object_id, $remark)
    {
        //插入数据
        DbManager::getInstance()->startTransactionWithCount('write');
        try {

            /**MemberModel 通过$this->user_id获取到用户信息,并且lockForUpdate*/
            $member = MemberModel::create()->connection('write')->lockForUpdate()->get($user_id);
            /**将提现代币score更新到ss_member中 MemberModel*/
            $memberData = [
                'score' => bcadd($member->score, $score, 2),
            ];
            if($memberData['score'] < 0){
                throw new \Exception('积分变动后小于0');
            }
            MemberModel::create()->updateData($memberData, ['id' => $user_id]);

            /**MemberScoreModel 将score的变动记录添加到ss_member_score中*/
            $data = [
                'user_id'      => $user_id,
                'score'        => bcmul($score, 1, 2),
                'before_score' => $member->score,
                'after_score'  => bcadd($member->score, $score, 2),
                'created_date' => date('Y-m-d'),
                'remark'       => $remark,
                'type'         => $type,
                'object_id'    => $object_id
            ];
            MemberScoreModel::create()->insertData($data);

            DbManager::getInstance()->commitWithCount('write');

            return $member;
        } catch (\Throwable $e) {
            DbManager::getInstance()->rollbackWithCount('write');
            CommonHelper::logException($e, '下单错误');
            throw $e;
        }
    }


    /**将30天之前的数据归档*/
    public function archiveRecord()
    {
        /**取出30天前(created_at)的前1000条记录*/
//        $last_date = date('Y-m-d', strtotime('-30 days'));
        $last_date = date('Y-m-01');
        $result = MemberScoreModel::makeQueryModel()
            ->where('created_at', $last_date . ' 00:00:00', '<')
            ->limit(MemberScoreModel::ARCHIVE_RECORD_LIMIT)//
            ->order('created_at', 'ASC')
            ->order('id', 'ASC')
            ->all();
        $data = [];
        if ($result){
            foreach ($result as $order) {
                $date = date('Ym', strtotime($order->created_at));
                if(!isset($data[$date])){
                    $data[$date] = [];
                }
                $order_array = $order->toRawArray();
                $data[$date][] = $order_array;
            }
            foreach ($data as $date => $orders){
                $table_name = MemberScoreModel::create()->getTableName() . '_' . $date;
                $this->createArchiveTable($date);
                try {
                    DbManager::getInstance()->startTransactionWithCount('write');
                    $order_ids = array_column($orders, 'id');
                    MemberScoreModel::create()->connection('write')->where(['id' => [$order_ids, 'in']])->lockForUpdate()->all();
                    /**归档记录*/
                    BaseModel::create()->insertMulti($orders, BaseModel::INSERT_INTO, [], $table_name);
                    /**删除记录*/
                    MemberScoreModel::create()->connection('write')->destroy(['id' => [$order_ids, 'in']]);

                    DbManager::getInstance()->commitWithCount('write');
                }catch (\Exception $e){
                    DbManager::getInstance()->rollbackWithCount('write');
                    throw $e;
                }
            }
        }
        return true;
    }

    /**创建归档的表*/
    public function createArchiveTable($date): void
    {
        $original_table = MemberScoreModel::create()->getTableName();
        $table_name =$original_table . '_' . $date;
        $query = new QueryBuilder();
        $sql = <<<sql
           
            CREATE TABLE If Not Exists {$table_name} LIKE {$original_table};
sql;
        $query->raw($sql);
        DbManager::getInstance()->query($query);
    }

    /**按月份分表*/
    public function archiveRecordMonth(){
        $table = MemberScoreModel::create()->getTableName();
        CommonHelper::archiveRecordMonth($table);
        return true;
//        $table_new = $table . '_new';
//        /**判断上一个月的分布是否存在*/
//        $last_month = date('Ym', strtotime(date('Y-m-01')) - 86400);
//        $table_nonth = $table . '_' . $last_month;
//        $query = new QueryBuilder();
//        $sql = "SHOW TABLES LIKE '". $table_nonth ."'";
//        $query->raw($sql);
//        $result = DbManager::getInstance()->query($query, true, 'write');
//        if ($result->getResult()) {
//            throw new \Exception('分表已存在');
//        }
//        $first_day = date('Y-m-01');
//        try {
//            DbManager::getInstance()->startTransactionWithCount('write');
//            $query = new QueryBuilder();
//            /**创建一个新表用于中转数据*/
//            $sql = "CREATE TABLE If Not Exists {$table_new} LIKE {$table}";
//            $query->raw($sql);
//            DbManager::getInstance()->query($query, false, 'write');
//            /**将本月新产生的数据写入到中专表*/
//            $sql = "INSERT INTO {$table_new}
//                    SELECT * FROM {$table} WHERE created_at>='{$first_day}';";#DATE_FORMAT(CURDATE(), '%Y-%m-01')
//            $query->raw($sql);
//            DbManager::getInstance()->query($query, false, 'write');
//            /**将表中本月的数据删掉*/
//            $sql = "DELETE FROM {$table} WHERE created_at>='{$first_day}';";
//            $query->raw($sql);
//            DbManager::getInstance()->query($query, false, 'write');
//            /**将表名修改为月份分表*/
//            $sql = "RENAME TABLE {$table} TO {$table_nonth};";
//            $query->raw($sql);
//            DbManager::getInstance()->query($query, false, 'write');
//            /**将中转表名修改为正式表名*/
//            $sql = "RENAME TABLE {$table_new} TO {$table};";
//            $query->raw($sql);
//            DbManager::getInstance()->query($query, false, 'write');
//
//            DbManager::getInstance()->commitWithCount('write');
//        }catch (\Exception $e){
//            DbManager::getInstance()->rollbackWithCount('write');
//            throw $e;
//        }
//        return true;
    }
}
